package avicit.bdp.dms.perm.service;

import avicit.bdp.common.base.BaseService;
import avicit.bdp.common.utils.BdpLogUtil;
import avicit.bdp.common.utils.CheckParaUtils;
import avicit.bdp.core.constant.Constants;
import avicit.bdp.dms.das.dto.BdpDasCategoryDTO;
import avicit.bdp.dms.das.service.BdpDasCategoryService;
import avicit.bdp.dms.perm.dao.CategoryPermDAO;
import avicit.bdp.dms.perm.dto.CategoryPermDTO;
import avicit.platform6.commons.utils.ComUtil;
import avicit.platform6.commons.utils.PojoUtil;
import avicit.platform6.core.exception.BusinessException;
import avicit.platform6.core.properties.PlatformConstant;
import com.alibaba.fastjson2.JSONObject;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @金航数码科技有限责任公司 @作者：developer @邮箱：developer@avic-digital.com @创建时间：
 * 2022-10-09 @类说明：CategoryPermService @修改记录： @注意事项： @主要功能：模型分类权限Service
 */
@Service
public class CategoryPermService extends BaseService<CategoryPermDAO, CategoryPermDTO> {

  private static final Logger logger = LoggerFactory.getLogger(CategoryPermService.class);

  /** 业务领域分类服务 */
  @Autowired private BdpDasCategoryService bdpDasCategoryService;

  /**
   * 新增数据权限
   * @param roleId 角色ID
   * @param nodeId 模型分类节点ID，多个节点使用英文逗号隔开
   * @param actionList 权限，0：查看;1：编辑;2：数据查看
   * 注意：
   *     1、支持分开授予查看、编辑、数据查看权限；
   *     2、VUE会将本次设置权限、已设置权限一并传入；
   */
  @Transactional
  public void addCategoryPerm(String roleId, String nodeId, List<Integer> actionList) {
    // step1:合法性检查
    checkAddCategoryPermValidity(roleId, nodeId, actionList);

    // step1:遍历分类节点，如果是非叶子节点，获取子节点，设置权限
    List<CategoryPermDTO> permDTOList = constructCategoryPerm(roleId, nodeId, actionList);

    // step2:根据roleId删除老权限
    for (String currNodeId : nodeId.trim().split(Constants.COMMA)) {
      this.mapper.deletePermByCond(roleId, currNodeId, null);
    }

    // step3:元数据持久化
    saveCategoryPerm2Db(permDTOList);

    String logTitle = "新增模型授权：角色id为【" + roleId + "】,模型分类id为【" + nodeId + "】,权限为【" + actionList + "】";
    BdpLogUtil.log("模型授权模块", logTitle, PlatformConstant.OpType.insert);
  }

  /**
   * 移除数据权限
   * 注意：
   *     1、新增授权时，如果为编辑或数据查看，多增加一条查看记录（related=1），删除时要一并删除
   * @param roleId 角色ID
   * @param nodeId 模型分类节点ID，多个节点使用英文逗号隔开
   * @param actionList 待移除权限，只能是0,1,2
   * @return
   */
  @Transactional
  public void removeCategoryPerm(String roleId, String nodeId, List<Integer> actionList) {
    // step1:合法性检查
    checkAddCategoryPermValidity(roleId, nodeId, null);
    if (CollectionUtils.isEmpty(actionList)) {
      return;
    }

    // step2:根据roleId删除老权限/删除附加权限
    for (String currNodeId : nodeId.trim().split(Constants.COMMA)) {
      if (StringUtils.isEmpty(currNodeId)) {
        continue;
      }

      // 删除权限
      this.mapper.deleteGrantedPermByCond(roleId, currNodeId, actionList);
      // 删除附加权限
      deleteRelatedPerm(roleId, currNodeId, actionList);
    }

    String logTitle = "移除模型授权：角色id为【" + roleId + "】,模型分类id为【" + nodeId + "】,权限为【" + actionList + "】";
    BdpLogUtil.log("模型授权模块", logTitle, PlatformConstant.OpType.delete);
  }

  /**
   * 根据节点ID删除权限(业务模块删除模型分类节点时同步删除权限)
   *
   * @param nodeId
   */
  public int deletePermByNodeId(String nodeId) {
    if (StringUtils.isEmpty(nodeId)) {
      return 0;
    }

    return this.mapper.deletePermByCond(null, nodeId, null);
  }

  /**
   * 新增权限时合法性检查
   *
   * @param roleId
   * @param nodeId
   * @param actionList
   */
  private void checkAddCategoryPermValidity(
      String roleId, String nodeId, List<Integer> actionList) {
    CheckParaUtils.checkStringValidity(roleId, logger, "角色ID为空");
    CheckParaUtils.checkStringValidity(nodeId, logger, "模型分类节点ID为空");

    /*
     * 场景1：设置权限，action不为null
     * 场景2：取消权限，action为null
     */
    if (CollectionUtils.isNotEmpty(actionList)) {
      for (Integer action : actionList) {
        if (action < Constants.QUERY_ACTION || action > Constants.DATA_VIEW_ACTION) {
          throw new BusinessException("权限范围[0,2], 当前值为：" + action);
        }
      }
    }
  }

  /**
   * 数据权限持久化到DB
   *
   * @param categoryPermDTOList
   * @return
   */
  private void saveCategoryPerm2Db(List<CategoryPermDTO> categoryPermDTOList) {
    if (CollectionUtils.isNotEmpty(categoryPermDTOList)) {
      this.mapper.batchInsertCategoryPermission(categoryPermDTOList);
    }
  }

  /**
   * 设置父子节点权限
   *
   * @param roleId
   * @param nodeId
   * @param actionList
   * @return
   */
  private List<CategoryPermDTO> constructCategoryPerm(
      String roleId, String nodeId, List<Integer> actionList) {
    List<CategoryPermDTO> resultList = new ArrayList<>();
    if (CollectionUtils.isEmpty(actionList)) {
      return resultList;
    }

    for (String currNodeId : Arrays.asList(nodeId.trim().split(Constants.COMMA))) {
      for (Integer action : actionList) {
        CategoryPermDTO perm = fillCategoryPermBaseInfo(roleId, currNodeId);
        perm.setAction(action);
        resultList.add(perm);

        // 如果为编辑权限或数据查看权限，默认具有查看权限
        if (action == Constants.EDIT_ACTION || action == Constants.DATA_VIEW_ACTION) {
          CategoryPermDTO queryPerm = fillCategoryPermBaseInfo(roleId, currNodeId);
          queryPerm.setRelated(1);
          queryPerm.setAction(Constants.QUERY_ACTION);
          resultList.add(queryPerm);
        }
      }
    }

    return resultList;
  }

  /**
   * 填充权限基本信息
   *
   * @param roleId
   * @param nodeId
   * @return
   */
  private CategoryPermDTO fillCategoryPermBaseInfo(String roleId, String nodeId) {
    BdpDasCategoryDTO dto = this.bdpDasCategoryService.selectByPrimaryKey(nodeId);
    if (dto == null) {
      throw new BusinessException("未找到分类节点,nodeId=" + nodeId);
    }

    CategoryPermDTO perm = new CategoryPermDTO();
    perm.setId(ComUtil.getId());
    perm.setName(dto.getName());
    perm.setRoleId(roleId);
    perm.setNodeId(nodeId);
    perm.setNodeName(dto.getName());
    perm.setEffect(Constants.EFFECT_ALLOW);
    perm.setDimension(Constants.DIMENSION_ROLE);
    perm.setRelated(0);
    perm.setRelatedNodeId(null);
    PojoUtil.setSysProperties(perm, PlatformConstant.OpType.insert);

    return perm;
  }

  /**
   * 删除附加权限
   * @param roleId
   * @param nodeId
   * @param actionList
   */
  private void deleteRelatedPerm(String roleId, String nodeId, List<Integer> actionList) {
    Set<Integer> actionSet = new HashSet<>(actionList);
    boolean isContainEditPerm = actionSet.contains(Constants.EDIT_ACTION) ? true : false;
    boolean isContainDataQueryPerm = actionSet.contains(Constants.DATA_VIEW_ACTION) ? true : false;
    if (!isContainEditPerm && !isContainDataQueryPerm) {
      return;
    }

    // 查询关联权限
    List<CategoryPermDTO> relatedPermList = this.mapper.getRelatedPermList(roleId, nodeId);
    if (CollectionUtils.isEmpty(relatedPermList)) {
      return;
    }

    int toDeleteNum = 0;
    // 待删除的包括编辑权限，删除一条附件权限记录
    if (isContainEditPerm) {
      toDeleteNum++;
    }
    // 待删除的包括数据查看权限，删除一条附件权限记录
    if (isContainDataQueryPerm) {
      toDeleteNum++;
    }

    for (int i = 0; i < toDeleteNum; i++) {
      if (CollectionUtils.isNotEmpty(relatedPermList)) {
        CategoryPermDTO relatedPerm = relatedPermList.remove(0);
        if (relatedPerm != null && StringUtils.isNotEmpty(relatedPerm.getId())) {
          this.deleteByPrimaryKey(relatedPerm.getId());
        }
      }
    }
  }
}
